package com.uxsino.simo.collector.connections;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.uxsino.commons.utils.StringUtils;
import com.uxsino.simo.connections.AbstractConnection;
import com.uxsino.simo.connections.exception.SimoConnectionException;
import com.uxsino.simo.connections.target.TCPTarget;

public class HTTPConnection extends AbstractConnection<TCPTarget> {
    static Logger logger = LoggerFactory.getLogger(HTTPConnection.class);

    private CloseableHttpClient client;

    private String urlBase;

    private static final int DEFAULT_TIMEOUT_MS = 10000;
    private int my_timeout_ms;
    
    @Override
    public int connect(TCPTarget target) {
        super.connect(target);
        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY,
            new UsernamePasswordCredentials(target.getUsername(), target.getPassword()));
        HttpClientBuilder builder = HttpClientBuilder.create();
        builder.setDefaultCredentialsProvider(credentialsProvider);
        client = builder.build();
        String str_timeout_ms = target.getMax_connected_times();
        try {
             my_timeout_ms = Integer.parseInt(str_timeout_ms);
		} catch (Exception e) {
			logger.error("HTTPConnectin setting timeout  incorrectly ,maybe stinrg but not a number ", e);
		}
        if(my_timeout_ms <=0) {
        	my_timeout_ms = DEFAULT_TIMEOUT_MS;
        }
        logger.info("连接时长为：    "+ my_timeout_ms);
        urlBase = "http://" + target.host + ":" + target.port;
        connected = true;   // not really connected
        state = 1;
        return state;
    }

    @Override
    public Object execCmd(Object cmdPattern) throws SimoConnectionException {
        String cmdStr = urlBase + cmdPattern.toString();
        HttpGet httpget = new HttpGet(cmdStr);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(my_timeout_ms)
            .setConnectTimeout(my_timeout_ms).setConnectionRequestTimeout(my_timeout_ms).build();
        httpget.setConfig(requestConfig);
        HttpEntity entity = null;
        try {
            HttpResponse response = client.execute(httpget);
            entity = response.getEntity();
            InputStream in = entity.getContent();

            ByteArrayOutputStream resultByte = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = in.read(buffer)) != -1) {
                resultByte.write(buffer, 0, length);
            }
            String result = resultByte.toString("UTF-8");
            return result;
        } catch (IOException e) {
            logger.error("error executing cmd in http connection", e);
            throw new SimoConnectionException(e);
        } finally {
            EntityUtils.consumeQuietly(entity);
        }
    }

    @Override
    public Object buildCmd(String cmdPattern, Map<String, String> args) {
        return cmdPattern;
    }

    @Override
    public int close() {

        try {
            if (client != null)
                client.close();
        } catch (IOException e) {
            logger.error("error closing http connection", e);
        }
        connected = false;

        super.close();
        return 0;
    }

    @Override
    public boolean testWithConnected(String cmdString, String resStart) {
        connected = false;
        String resultStr = null;
        try {
            resultStr = (String) execCmd(cmdString);
        } catch (SimoConnectionException e) {
            logger.error("error executing cmd in http connection", e);
        }
        if (resultStr != null && resStart != null) {
            if (resStart.startsWith("indexOf:")) {
                if (resultStr.indexOf(resStart.substring(8)) != -1) {
                    connected = true;
                }
            } else if (resStart.startsWith("startsWith:")) {
                if (resultStr.startsWith(resStart.substring(11))) {
                    connected = true;
                }
            }
        }
        logger.info("http connection test result: {}", connected);
        return connected;
    }

}
